package org.apache.james.hibernate;

import java.util.List;

import javax.mail.Flags;

import org.apache.james.hibernate.entity.DbMailbox;
import org.apache.james.hibernate.entity.Group;
import org.apache.james.hibernate.entity.ImapUserInfo;
import org.apache.james.hibernate.entity.Mail;
import org.apache.james.hibernate.entity.MailFlag;
import org.apache.james.hibernate.entity.NamespaceImpl;
import org.apache.james.mailboxmanager.GeneralMessageSet;
import org.apache.james.mailboxmanager.MailboxManagerException;
import org.apache.james.mailboxmanager.MessageResult;
import org.apache.james.mailboxmanager.Namespaces;
import org.apache.james.mailboxmanager.SearchParameters;

public interface MailboxPersistenceManager {

	/**
	 * initilise the MailStore. The mail store can be null, in that case the decision is for the implementation what to do. 
	 * The hibernate based one is internally implements the MailStore interface also, so it will use that.
	 * 
	 * @see DbMailboxManager
	 * @see MailStore
	 * @param mailStore
	 */
	public abstract void setupMailStore(MailStore mailStore);

	public MailStore getMailStore();
	
	public abstract ImapUserInfo getUserinfo(String username);

	/**
	 * creates a new Namespace object with the given parameters.
	 * @param name
	 * @param description
	 * @param repository
	 * @param defaultShared
	 * @param defaultUser
	 * @return
	 */
	public abstract NamespaceImpl createNewNamespace(String name,
			String description, String repository, boolean defaultShared,
			boolean defaultUser);

	/**
	 * retrieves a Group object by name.
	 * 
	 * @see Group
	 * @param name
	 *            the name of the group
	 * @return
	 */
	public abstract Group getGroup(String name);

	/**
	 * retrieves a NamespaceImpl object by name.
	 * 
	 * @see NamespaceImpl
	 * @param name
	 *            the name of the namespace
	 * @return
	 */
	public abstract NamespaceImpl getNamespace(String name);

	public abstract Namespaces getUserNamespaces(String name);

	@SuppressWarnings("unchecked")
	public abstract ImapUserInfo createImapUserInfo(String username);

	public abstract MailFlag appendAsNewMail(ImapUserInfo user,
			DbMailbox mailbox, Mail mail, Flags javamailFlag);

	public abstract DbMailbox createMailbox(ImapUserInfo userInfo,
			NamespaceImpl ns, String mailboxName);

	public abstract boolean existsMailbox(ImapUserInfo userInfo,
			String mailboxName);

	public abstract boolean createInbox(ImapUserInfo userInfo);

	@SuppressWarnings("unchecked")
	public abstract List<String> listMailboxNames(ImapUserInfo userInfo,
			String base, String expression, boolean subscribed);

	public abstract void deleteMailbox(ImapUserInfo userInfo, String mailboxName);

	public abstract DbMailbox getMailbox(String mailboxName);

	/**
	 * return a mailbox object if it's exists, null when not.
	 * @param id the id of the mailbox
	 * @return
	 */
	public abstract DbMailbox getMailbox(int id);

	@SuppressWarnings("unchecked")
	public abstract MessageResult[] getMessagesFlags(GeneralMessageSet set,
			ImapUserInfo user, DbMailbox mailbox)
			throws MailboxManagerException;

	@SuppressWarnings("unchecked")
	public abstract MessageResult[] getMessages(GeneralMessageSet set,
			ImapUserInfo user, DbMailbox mailbox, boolean includeBody,
			boolean includeHeader) throws MailboxManagerException;

	public abstract int getMessageCount(DbMailbox mailbox, ImapUserInfo user,
			String flags);

	public abstract Long getFirstUnseenUid(DbMailbox mailbox, ImapUserInfo user);

	public abstract void setFlags(Flags flags, boolean replace,
			boolean addFlags, GeneralMessageSet set, DbMailbox mailbox,
			ImapUserInfo user) throws MailboxManagerException;

	public abstract MessageResult[] searchUids(DbMailbox mailbox,
			ImapUserInfo user, SearchParameters searchTerm)
			throws MailboxManagerException;

	/**
	 * expunges the deleted messages from the given mailbox, by the given user. If the owner of the mailbox is not the user, 
	 * then nothing will happens.
	 * @param mailbox
	 * @param user
	 * @return
	 */
	public abstract List<Integer> expungeAll(DbMailbox mailbox,
			ImapUserInfo user);

	/**
	 * renames the mailbox if the user is the owner of the mailbox, and the new name is in the same namespace.
	 * @param userInfo
	 * @param from
	 * @param to
	 * @throws MailboxManagerException 
	 */
	public abstract void renameMailbox(ImapUserInfo userInfo, String from,
			String to) throws MailboxManagerException;

}